<!DOCTYPE html>
<html>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script type="importmap">
{
  "imports": {
    "./resources/log.js?pipe=sub&name=ResolvesToBadHash": "./resources/log.js?pipe=sub&name=BadHash",
    "./resources/log.js?pipe=sub&name=ResolvesToNoHash": "./resources/log.js?pipe=sub&name=NoHash",
    "./resources/log.js?pipe=sub&name=GoodHash": "./resources/log.js?pipe=sub&name=GoodHash",
    "bare": "./resources/log.js?pipe=sub&name=BareURL",
    "bare2": "./resources/log.js?pipe=sub&name=F"
  },
  "integrity": {
    "./resources/log.js?pipe=sub&name=BadHash": "sha384-foobar",
    "./resources/log.js?pipe=sub&name=ResolvesToNoHash": "sha384-foobar",
    "./resources/log.js?pipe=sub&name=GoodHash": "sha384-SwfgBqInhSlLziU454cYhGgwPpae+d3VHZcY+vjZIO/gxRGt2u3Jsfyvure/Ww0u",
    "./resources/log.js?pipe=sub&name=InvalidExtra": "sha384-WsKk8nzJFPhk/4pWR4LYoPhEu3xaAc6PdIm4vmqoZVWqEgMYmZgOg9XJKxgD1+8v foobar-rOJN8igD0+jW6lwNN3+InhXTgQztVHlq/HJ0riswXp8kMoiIDx5JpmCwuVem6Ll9q2LFNSu1xq23bsBMMQk1rg==",
    "./resources/log.js?pipe=sub&name=Suffix": "sha384-lbOWldbmji7sCHI/L8iVJ+elmFIMp41p+aYOLxqQfZMqtoFeHFVe/ASRA0IyZ1/9?foobar",
    "./resources/log.js?pipe=sub&name=Multiple": "sha384-foobar sha512-rOJN8igD0+jW6lwNN3+InhXTgQztVHlq/HJ0riswXp8kMoiIDx5JpmCwuVem6Ll9q2LFNSu1xq23bsBMMQk1rg==",
    "./resources/log.js?pipe=sub&name=BadHashWithNoImport": "sha384-foobar",
    "./resources/log.js?pipe=sub&name=BareURL": "sha384-foobar",
    "./resources/log.js?pipe=sub&name=EventHandlerPass": "sha384-d4yrBK8a55vlyYz2QEnlaU64PPpdKBkblD2KmfozI61mC1ij6RrZJaGCTsVxPuJ2",
    "./resources/log.js?pipe=sub&name=EventHandlerFail": "sha384-foobar",
    "bare2": "sha384-foobar",
    "resources/log.js?pipe=sub&name=Bare": "sha384-foobar"
  }
}
</script>
<script>
let log;
const test_not_loaded = (url, description) => {
  promise_test(async t => {
    log = [];
    await promise_rejects_js(t, TypeError, import(url));
    assert_array_equals(log, []);
  }, description);
};

const test_loaded = (url, log_expectation, description) => {
  promise_test(async t => {
    log = [];
    await import(url);
    assert_array_equals(log, log_expectation);
  }, description);
};

test_not_loaded(
  "./resources/log.js?pipe=sub&name=ResolvesToBadHash",
  "script was not loaded, as its resolved URL failed its integrity check"
);
test_loaded(
  "./resources/log.js?pipe=sub&name=ResolvesToNoHash",
  ["log:NoHash"],
  "script was loaded, as its resolved URL had no integrity check, despite its specifier having one"
);
test_loaded(
  "./resources/log.js?pipe=sub&name=GoodHash",
  ["log:GoodHash"],
  "script was loaded, as its integrity check passed"
);
test_not_loaded(
  "./resources/log.js?pipe=sub&name=BadHashWithNoImport",
  "Script with no import definition was not loaded, as it failed its integrity check"
);
test_not_loaded(
  "bare",
  "Bare specifier script was not loaded, as it failed its integrity check"
);
test_loaded(
  "bare2",
  ["log:F"],
  "Bare specifier used for integrity loaded, as its definition should have used the URL"
);
test_loaded(
  "./resources/log.js?pipe=sub&name=InvalidExtra",
  ["log:InvalidExtra"],
  "script was loaded, as its integrity check passed, despite having an extra invalid hash"
);
test_loaded(
  "./resources/log.js?pipe=sub&name=Suffix",
  ["log:Suffix"],
  "script was loaded, as its integrity check passed, despite having an invalid suffix"
);
test_loaded(
  "./resources/log.js?pipe=sub&name=Multiple",
  ["log:Multiple"],
  "script was loaded, as its integrity check passed given multiple hashes. This also makes sure that the larger hash is picked"
);
test_loaded(
  "./resources/log.js?pipe=sub&name=Bare",
  ["log:Bare"],
  "script was loaded, as its integrity check was ignored, as it was defined using a URL that looks like a bare specifier"
);

promise_test(async () => {
  log = [];
  const img = new Image();
  const promise = new Promise((resolve, reject) => {
    img.onload = () => {
      import('./resources/log.js?pipe=sub&name=EventHandlerPass').then(resolve).catch(reject);
    };
    img.src = "/images/green.png?1";
  });

  await promise;
  assert_equals(log.length, 1);
  assert_equals(log[0], "log:EventHandlerPass");
}, "Script imported inside an event handler was loaded as its valid integrity check passed");

promise_test(async t => {
  log = [];
  const img = new Image();
  const promise = new Promise((resolve, reject) => {
    img.onload = () => {
      import('./resources/log.js?pipe=sub&name=EventHandlerFail').then(resolve).catch(reject);
    };
    img.src = "/images/green.png?2";
  });

  await promise_rejects_js(t, TypeError, promise);
}, "Script imported inside an event handler was not loaded as its integrity check failed");
</script>

